#include<stdio.h> 
#include<stdlib.h>
#include<sys/types.h> 
#include<sys/stat.h> 
#include<fcntl.h> 
#include<unistd.h>
#include<string.h> 
#include<linux/input.h>
#include <sys/mman.h> 

#define video_order_pre "/mplayer -slave -input file=/my_fifo -zoom -x 800 -y 380 "

typedef struct ListNode
{
	int vedio_state;
	struct ListNode* prev;
	struct ListNode* next;
} LinkList;

/****** 全局变量定义区 ******/

struct input_event touch;
int touch_x , touch_y;                  //获取触摸屏坐标
short video_state = 0;                  //视频播放状态位
LinkList* current_video;                //当前指向指针
LinkList* first_newNode; 
int video_fd_bottom_start;              //视频播放底部文件描述符
int video_fd_bottom_pause;              //视频暂停底部文件描述符
int video_fd_top;                       //视频选择文件描述符
int touch_fd;                           //触摸屏文件描述符
int fifo_fd;                            //管道文件描述符
int lcd_fd ;                            //LCD文件描述符
LinkList* newNode_1;                    //视频指针
LinkList* newNode_2;
LinkList* newNode_3;
LinkList* newNode_4;
LinkList* temp;

/****** 全局变量定义区 ******/


// 从设备文件读取相应的触摸屏信息 read 
void get_touch() 
{ 
 
 // sizeof() ---> 可以用于获得结构体类型大小 
 read(touch_fd,&touch,sizeof(touch)); 

 // 3. 进一步的处理 
 if( touch.type == EV_ABS && touch.code == ABS_X ) touch_x = touch.value*800/1024; 
 if( touch.type == EV_ABS && touch.code == ABS_Y ) touch_y = touch.value*480/600; 
} 

//视频首页触摸屏控制
int get_touch_event() 
{ 
    int event_flags = -1; // 触摸屏动作标志位 

    while(1) 
    { 
        get_touch(); // 获取触摸屏信息，以及X，Y决定坐标事件处理  


        if( touch.type == EV_KEY && touch.code == BTN_TOUCH && touch.value == 0)  // 手指离开触摸屏
        { 

            printf("手指松开触摸屏\n");

            event_flags = 0; // 单击动作 

            if(touch_x >= 0 && touch_x < 400 && touch_y >= 0 && touch_y < 240) event_flags = 1; //加音量
            if(touch_x >= 400 && touch_x < 800 && touch_y >= 0 && touch_y < 240) event_flags = 2; //减音量
            if(touch_x >= 0 && touch_x < 400 && touch_y >= 240 && touch_y < 480) event_flags = 3; //上一个视频
            if(touch_x >= 400 && touch_x < 800 && touch_y >= 240 && touch_y < 480) event_flags = 4; //暂停/开始
            //if(touch_x >= 700 && touch_x < 800 && touch_y >= 380 && touch_y < 480) event_flags = 6; //退出

            return event_flags; // 返回触摸屏动作标志位 
        } 
    } 
} 

//视频播放触摸屏控制
int get_touch_event_1() 
{ 
    int event_flags = -1; // 触摸屏动作标志位  

    while(1) 
    { 
        get_touch(); // 获取触摸屏信息，以及X，Y决定坐标事件处理 


        if( touch.type == EV_KEY && touch.code == BTN_TOUCH && touch.value == 0 )  // 手指离开触摸屏
        { 

            printf("手指松开触摸屏\n");

            if(touch_x >= 0 && touch_x < 100 && touch_y >= 380 && touch_y < 480) event_flags = 1; //加音量
            if(touch_x >= 100 && touch_x < 200 && touch_y >= 380 && touch_y < 480) event_flags = 2; //减音量
            if(touch_x >= 250 && touch_x < 350 && touch_y >= 380 && touch_y < 480) event_flags = 3; //上一个视频
            if(touch_x >= 350 && touch_x < 450 && touch_y >= 380 && touch_y < 480) event_flags = 4; //暂停/开始
            if(touch_x >= 450 && touch_x < 550 && touch_y >= 380 && touch_y < 480) event_flags = 5; //下一个视频
            if(touch_x >= 700 && touch_x < 800 && touch_y >= 380 && touch_y < 480) event_flags = 6; //退出
            if(touch_x >= 0 && touch_x < 400 && touch_y >= 0 && touch_y < 380) event_flags = 7;     //后退5秒
            if(touch_x >= 400 && touch_x < 800 && touch_y >= 0 && touch_y < 380) event_flags = 8;   //快进5秒


            return event_flags; // 返回触摸屏动作标志位 
        } 
    } 
} 

//底部开始按钮初始化
void bottom_init_start()
{ 
    int * mmap_star = mmap(NULL,800*480*4,PROT_READ | PROT_WRITE,MAP_SHARED,lcd_fd,0); 

    if(mmap_star == MAP_FAILED) 
    { 
    printf("映射失败！\n"); 
    return ; 
    } 

    off_t lseek_ret = lseek(video_fd_bottom_start,54,SEEK_SET);//鐠哄疇绻冨��鈧�婢讹拷54娑擄拷鐎涙�勫Ν

    char rgb[800*100*3]; 
    int read_ret = read(video_fd_bottom_start,rgb,800*100*3); 


    int x; 
    int y; 
    for(y=0;y<100;y++) 
    { 
        for(x=0;x<800;x++) 
        { 
            *(mmap_star + 800*(479-y)+x) = rgb[3*(800*y+x)]<<0 | rgb[3*(800*y+x)+1]<<8 | rgb[3*(800*y+x)+2] <<16;

        } 
    } 

    munmap(mmap_star,480*800*4);

}

//底部暂停按钮初始化
void bottom_init_pause()
{ 
    int * mmap_star = mmap(NULL,800*480*4,PROT_READ | PROT_WRITE,MAP_SHARED,lcd_fd,0); 

    if(mmap_star == MAP_FAILED) 
    { 
    printf("映射失败！\n");  
    return ; 
    } 

    off_t lseek_ret = lseek(video_fd_bottom_pause,54,SEEK_SET);//鐠哄疇绻冨��鈧�婢讹拷54娑擄拷鐎涙�勫Ν

    char rgb[800*100*3]; 
    int read_ret = read(video_fd_bottom_pause,rgb,800*100*3); 


    int x; 
    int y; 
    for(y=0;y<100;y++) 
    { 
        for(x=0;x<800;x++) 
        { 
            *(mmap_star + 800*(479-y)+x) = rgb[3*(800*y+x)]<<0 | rgb[3*(800*y+x)+1]<<8 | rgb[3*(800*y+x)+2] <<16;

        } 
    } 

    munmap(mmap_star,480*800*4);

}

//初始化内存空间
LinkList* video_init()
{
    //动态申请内存空间
    newNode_1 = (LinkList*)malloc(sizeof(LinkList));
    newNode_2 = (LinkList*)malloc(sizeof(LinkList));
    newNode_3 = (LinkList*)malloc(sizeof(LinkList));
    newNode_4 = (LinkList*)malloc(sizeof(LinkList));
    first_newNode = (LinkList*)malloc(sizeof(LinkList));

    if(newNode_1 == NULL || newNode_2 == NULL || newNode_3 == NULL || newNode_4 == NULL || first_newNode == NULL)
	{
		printf("分配内存失败\n");
		exit(-1);
	}

    newNode_1->next = newNode_2; 
    newNode_1->prev = newNode_4;
    newNode_1->vedio_state = 1;


    newNode_2->next = newNode_3;
    newNode_2->prev = newNode_1;
    newNode_2->vedio_state = 2;
   

    newNode_3->next = newNode_4;
    newNode_3->prev = newNode_2;
    newNode_3->vedio_state = 3;
   

    newNode_4->next = newNode_1;
    newNode_4->prev = newNode_3;
    newNode_4->vedio_state = 4;


    first_newNode->next = newNode_4;
    first_newNode->prev = NULL;
    first_newNode->vedio_state = 5;

    return newNode_1;

}

//视频播放控制
void video_play(LinkList* Node)
{

    switch(Node->vedio_state)
    {
        case 1: system("/mplayer -slave -input file=/my_fifo -zoom -x 800 -y 380 /mdata/video/1.avi &"); break;
        case 2: system("/mplayer -slave -input file=/my_fifo -zoom -x 800 -y 380 /mdata/video/2.avi &"); break;
        case 3: system("/mplayer -slave -input file=/my_fifo -zoom -x 800 -y 380 /mdata/video/3.avi &"); break;
        case 4: system("/mplayer -slave -input file=/my_fifo -zoom -x 800 -y 380 /mdata/video/4.avi &"); break;
        case 5: printf("输出的是第五个视频\n");
    }

}

//视频首页渲染
void video_top_mmap()
{
    int * mmap_star = mmap(NULL,800*480*4,PROT_READ | PROT_WRITE,MAP_SHARED,lcd_fd,0); 


    if(mmap_star == MAP_FAILED) 
    { 
    printf("映射失败！\n"); 
    return ; 
    } 

    off_t lseek_ret = lseek(video_fd_top,54,SEEK_SET);//跳过开头54个字节

    char rgb[800*480*3]; 
    int read_ret = read(video_fd_top,rgb,800*480*3); 


    int x; 
    int y; 
    for(y=0;y<480;y++) 
    { 
        for(x=0;x<800;x++) 
        { 
            *(mmap_star + 800*(479-y)+x) = rgb[3*(800*y+x)]<<0 | rgb[3*(800*y+x)+1]<<8 | rgb[3*(800*y+x)+2] <<16;

        } 
    } 

    munmap(mmap_star,480*800*4);
}

int main()
{

    
    /****** 获取文件描述符 ******/
    touch_fd = open("/dev/input/event0",O_RDWR); //打开触摸屏设备文件
    lcd_fd = open("/dev/fb0",O_RDWR);
    if(access("/my_fifo" , F_OK) )  mkfifo("/my_fifo",0777);
    fifo_fd = open("/my_fifo",O_RDWR);
    video_fd_bottom_start = open("/mdata/video/bottom_start.bmp",O_RDWR); //打开底部按钮文件
    video_fd_bottom_pause = open("/mdata/video/bottom_pause.bmp",O_RDWR);
    video_fd_top = open("/mdata/video/video_top.bmp",O_RDWR);
    
    /****** 获取文件描述符 ******/

    if(fifo_fd == -1 || touch_fd == -1 || video_fd_bottom_start == -1 || video_fd_bottom_pause == -1 || lcd_fd == -1 || video_fd_top == -1)
    {
        perror("文件打开失败\n");
        return -1;
    }

    /****** 程序&变量初始化区 ******/

    temp = video_init();                    //开辟内存空间，并对指针头赋值
    first_newNode->next = temp;
    current_video = first_newNode->next;
    video_top_mmap();                       //视频选择界面渲染 


    /****** 程序&变量初始化区 ******/


    /****** 视频选择界面 ******/
     int flag_x_y = get_touch_event();

        bottom_init_start();                //加载底部按钮

        if(flag_x_y == 0 ) 
        { 
            printf("单击无效区域！\n"); 

        }  
        else if(flag_x_y == 1 )  
        { 
            printf("以视频结点一作为头指针\n");
            first_newNode->next = newNode_1;
            first_newNode->prev = newNode_1->prev;
            current_video = first_newNode->next;
            video_play(current_video);
            
        } 
        else if(flag_x_y == 2 ) 
        { 
            printf("以视频结点二作为头指针\n");
            first_newNode->next = newNode_2;
            first_newNode->prev = newNode_2->prev;
            current_video = first_newNode->next;
            video_play(current_video);

        }
        else if(flag_x_y == 3) 
        {
            printf("以视频结点三作为头指针\n");
            first_newNode->next = newNode_3;
            first_newNode->prev = newNode_3->prev;
            current_video = first_newNode->next;
            video_play(current_video);
           
        } 
        else if(flag_x_y == 4) 
        {
           printf("以视频结点四作为头指针\n");
            first_newNode->next = newNode_4;
            first_newNode->prev = newNode_4->prev;
            current_video = first_newNode->next;
            video_play(current_video);
        }

        /****** 视频选择界面 ******/

        while(1) 
        { 

            int flag_x_y_2 = get_touch_event_1();

            if(flag_x_y_2 == 0) 
            { 
                printf("单击！\n"); 
            }  
            else if(flag_x_y_2 == 1 ) 
            { 
                printf("增加音量！\n");
                write(fifo_fd,"volume 30 \n",strlen("volume 30 \n"));
            } 
            else if(flag_x_y_2 == 2 ) 
            { 
                printf("减少音量！\n");
                write(fifo_fd,"volume -30 \n",strlen("volume -30 \n"));
            }
            else if(flag_x_y_2 == 3) 
            {
                printf("上一个视频\n");
                system("killall -SIGKILL mplayer");//关闭现在播放的视频
                current_video = current_video -> prev;
                video_play(current_video);
            
            } 
            else if(flag_x_y_2 == 4 ) 
            {   

                if(video_state == 0)
                {
                    printf("视频暂停\n");
                    write(fifo_fd,"pause\n",strlen("pause\n"));
                    bottom_init_pause(); //渲染底部按键
                    video_state = 1;
                }
                else if(video_state == 1)
                {
                    printf("视频继续\n");
                    write(fifo_fd,"pause\n",strlen("pause\n"));
                    bottom_init_start();
                    video_state = 0;
                }

            }
            else if(flag_x_y_2 == 5)
            {
                printf("下一个视频\n");
                system("killall -SIGKILL mplayer");//关闭现在播放的视频
                current_video = current_video -> next;
                video_play(current_video);

            }
            else if(flag_x_y_2 == 6)
            {
                printf("退出\n");
                system("killall -SIGKILL mplayer");

                return 0;
            }
            else if(flag_x_y_2 == 7) 
            {
                printf("后退5秒\n");
                write(fifo_fd,"seek -5\n",strlen("seek -5\n"));
            }
            else if(flag_x_y_2 == 8)
            {
                printf("快进5秒\n");
                write(fifo_fd,"seek 5\n",strlen("seek 5\n"));
            }
        }

            return 0;


}